package com.imooc.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.imooc.enums.CommentLevel;
import com.imooc.mapper.ItemsCommentsMapper;
import com.imooc.mapper.ItemsImgMapper;
import com.imooc.mapper.ItemsMapper;
import com.imooc.mapper.ItemsMapperCustom;
import com.imooc.mapper.ItemsParamMapper;
import com.imooc.mapper.ItemsSpecMapper;
import com.imooc.pojo.Items;
import com.imooc.pojo.ItemsComments;
import com.imooc.pojo.ItemsImg;
import com.imooc.pojo.ItemsParam;
import com.imooc.pojo.ItemsSpec;
import com.imooc.pojo.vo.CommentLevelCountsVO;
import com.imooc.pojo.vo.ItemCommentVO;
import com.imooc.pojo.vo.SearchItemsVO;
import com.imooc.pojo.vo.ShopcartVO;
import com.imooc.service.ItemService;
import com.imooc.utils.DesensitizationUtil;
import com.imooc.utils.PagedGridResult;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
@AllArgsConstructor
public class ItemServiceImpl implements ItemService {

  private final ItemsMapper itemsMapper;

  private final ItemsImgMapper itemsImgMapper;

  private final ItemsSpecMapper itemsSpecMapper;

  private final ItemsParamMapper itemsParamMapper;

  private final ItemsCommentsMapper itemsCommentsMapper;

  private final ItemsMapperCustom itemsMapperCustom;

  @Transactional(rollbackFor = Exception.class, propagation = Propagation.SUPPORTS)
  @Override
  public Items queryItemById(String itemId) {
    return itemsMapper.selectById(itemId);
  }

  @Transactional(rollbackFor = Exception.class, propagation = Propagation.SUPPORTS)
  @Override
  public List<ItemsImg> queryItemImgList(String itemId) {
    return itemsImgMapper.selectList(Wrappers.<ItemsImg>lambdaQuery()
        .eq(ItemsImg::getItemId, itemId));
  }

  @Transactional(rollbackFor = Exception.class, propagation = Propagation.SUPPORTS)
  @Override
  public List<ItemsSpec> queryItemSpecList(String itemId) {
    return itemsSpecMapper.selectList(Wrappers.<ItemsSpec>lambdaQuery()
        .eq(ItemsSpec::getItemId, itemId));
  }

  @Transactional(rollbackFor = Exception.class, propagation = Propagation.SUPPORTS)
  @Override
  public ItemsParam queryItemParam(String itemId) {
    return itemsParamMapper.selectOne(Wrappers.<ItemsParam>lambdaQuery()
        .eq(ItemsParam::getItemId, itemId));
  }

  @Transactional(rollbackFor = Exception.class, propagation = Propagation.SUPPORTS)
  @Override
  public CommentLevelCountsVO queryCommentCounts(String itemId) {
    Integer goodCounts = getCommentCounts(itemId, CommentLevel.GOOD.type);
    Integer normalCounts = getCommentCounts(itemId, CommentLevel.NORMAL.type);
    Integer badCounts = getCommentCounts(itemId, CommentLevel.BAD.type);
    Integer totalCounts = goodCounts + normalCounts + badCounts;
    CommentLevelCountsVO countsVO = new CommentLevelCountsVO();
    countsVO.setTotalCounts(totalCounts);
    countsVO.setGoodCounts(goodCounts);
    countsVO.setNormalCounts(normalCounts);
    countsVO.setBadCounts(badCounts);
    return countsVO;
  }

  @Transactional(rollbackFor = Exception.class, propagation = Propagation.SUPPORTS)
  Integer getCommentCounts(String itemId, Integer level) {
    return itemsCommentsMapper.selectCount(Wrappers.<ItemsComments>lambdaQuery()
        .eq(ObjectUtil.isNotNull(level), ItemsComments::getCommentLevel, level)
        .eq(ItemsComments::getItemId, itemId));
  }

  @Transactional(rollbackFor = Exception.class, propagation = Propagation.SUPPORTS)
  @Override
  public PagedGridResult queryPagedComments(String itemId,
      Integer level,
      Integer page,
      Integer pageSize) {

    Map<String, Object> map = new HashMap<>();
    map.put("itemId", itemId);
    map.put("level", level);

    // mybatis-pagehelper

    /**
     * page: 第几页
     * pageSize: 每页显示条数
     */
    PageHelper.startPage(page, pageSize);

    List<ItemCommentVO> list = itemsMapperCustom.queryItemComments(map);
    for (ItemCommentVO vo : list) {
      vo.setNickname(DesensitizationUtil.commonDisplay(vo.getNickname()));
    }

    return setterPagedGrid(list, page);
  }

  private PagedGridResult setterPagedGrid(List<?> list, Integer page) {
    PageInfo<?> pageList = new PageInfo<>(list);
    PagedGridResult grid = new PagedGridResult();
    grid.setPage(page);
    grid.setRows(list);
    grid.setTotal(pageList.getPages());
    grid.setRecords(pageList.getTotal());
    return grid;
  }

  @Transactional(rollbackFor = Exception.class, propagation = Propagation.SUPPORTS)
  @Override
  public PagedGridResult searhItems(String keywords, String sort, Integer page, Integer pageSize) {

    Map<String, Object> map = new HashMap<>();
    map.put("keywords", keywords);
    map.put("sort", sort);

    PageHelper.startPage(page, pageSize);
    List<SearchItemsVO> list = itemsMapperCustom.searchItems(map);

    return setterPagedGrid(list, page);
  }

  @Transactional(rollbackFor = Exception.class, propagation = Propagation.SUPPORTS)
  @Override
  public PagedGridResult searhItems(Integer catId, String sort, Integer page, Integer pageSize) {
    Map<String, Object> map = new HashMap<>();
    map.put("catId", catId);
    map.put("sort", sort);

    PageHelper.startPage(page, pageSize);
    List<SearchItemsVO> list = itemsMapperCustom.searchItemsByThirdCat(map);

    return setterPagedGrid(list, page);
  }

  @Transactional(rollbackFor = Exception.class, propagation = Propagation.SUPPORTS)
  @Override
  public List<ShopcartVO> queryItemsBySpecIds(String specIds) {

    String[] ids = specIds.split(",");
    List<String> specIdsList = new ArrayList<>();
    Collections.addAll(specIdsList, ids);

    return itemsMapperCustom.queryItemsBySpecIds(specIdsList);
  }

  @Transactional(rollbackFor = Exception.class, propagation = Propagation.SUPPORTS)
  @Override
  public ItemsSpec queryItemSpecById(String specId) {
    return itemsSpecMapper.selectById(specId);
  }

  @Transactional(rollbackFor = Exception.class, propagation = Propagation.SUPPORTS)
  @Override
  public String queryItemMainImgById(String itemId) {
    ItemsImg result = itemsImgMapper.selectOne(Wrappers.<ItemsImg>lambdaQuery()
        .eq(ItemsImg::getItemId, itemId));
    return result != null ? result.getUrl() : "";
  }

  @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
  @Override
  public void decreaseItemSpecStock(String specId, int buyCounts) {
    // synchronized 不推荐使用，集群下无用，性能低下
    // 锁数据库: 不推荐，导致数据库性能低下
    // 分布式锁 zookeeper redis

    // lockUtil.getLock(); -- 加锁

    // 1. 查询库存
//        int stock = 10;

    // 2. 判断库存，是否能够减少到0以下
//        if (stock - buyCounts < 0) {
    // 提示用户库存不够
//            10 - 3 -3 - 5 = -1
//        }

    // lockUtil.unLock(); -- 解锁
    int result = itemsMapperCustom.decreaseItemSpecStock(specId, buyCounts);
    if (result != 1) {
      throw new RuntimeException("订单创建失败，原因：库存不足!");
    }
  }
}